Dynomotion

Group: DynoMotion Message: 10915 From: bknighton28 Date: 1/25/2015
Subject: polygonal turning using kflop
I have a differential encoder on my spindle for threading and its good so far.
But before embarking on a steep learning curve I would like to ask the group or Tom if polygonal turning is at least plausible. my system is a kflop and snapamp. I would like to be able to turn or bore, at slow spindle speed, shapes with the x lathe axis position as a polar function of the spindle position.
it is reasonable to wish a c program on the kflops, called from Mach as an M code, that the implements a polar function using the spindle position and x axis?
Group: DynoMotion Message: 10920 From: Tom Kerekes Date: 1/25/2015
Subject: Re: polygonal turning using kflop
Hi Bill,

That sounds very interesting - can't wait for the video :)

I would think it could be accomplished in a few lines of C code to generate X as a function of Spindle position.  How well it works of course would depend on Spindle Speed and the performance of your X axis.

Regards
TK

Group: DynoMotion Message: 10921 From: Moray Cuthill Date: 1/25/2015
Subject: Re: polygonal turning using kflop
Can I join the list for watching the video?
 
Polygonal turning is something I'd like to be able to do, but don't have a suitable machine (yet!).
 
For those who don't know what it is, the animation on this page explains it pretty well - http://www.nittopolygon.com/11polygon.html
I think the Polygon Machines are mostly directdrive using a shaft from the headstock, however quite a few CNC lathes with live tooling are capable of it using software syncronisation.
 
It doesn't produce perfect flats, however with a suitable choice of cutter diameter, number of cutters and drive ratio (I do have a tooling catalogue somewhere that lists the recommended combinations if anybody is interested), it produces flats that are good enough for spanners/sockets, which is where polygonal turning is mainly used.
 
Moray

On Sun, Jan 25, 2015 at 8:45 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi Bill,

That sounds very interesting - can't wait for the video :)

I would think it could be accomplished in a few lines of C code to generate X as a function of Spindle position.  How well it works of course would depend on Spindle Speed and the performance of your X axis.

Regards
TK

Group: DynoMotion Message: 10925 From: bknighton28 Date: 1/26/2015
Subject: Re: polygonal turning using kflop
my immediate use is boring holes in shafts that have flats in the bottom to engage a motor drive shaft that has flats on the end. now I do it with 1/8 endmill cnc and the grind the corners with a dremel by hand. it's ugly. there can be some play so perfection is not required. I hate delivering expensive parts with this kind of work inside.
Group: DynoMotion Message: 10926 From: bknighton28 Date: 1/26/2015
Subject: Re: polygonal turning using kflop
Would I copy all of the c program that is read on mach3 resets  into the beginning of the proposed polygonal turning program to get the motor and encoder assignments and tuning?
Group: DynoMotion Message: 10927 From: bknighton28 Date: 1/26/2015
Subject: Re: polygonal turning using kflop
Is there a way to set up an interrupt and a service routine so that when the spindle encoder ticks the service routine could calculate and command a servo move? Or is that the wrong strategy?  Maybe instead a timer goes off periodically and the servo position is commanded based on the spindle encoder?
  Could something as crude as a loop that constantly looks at the spindle encoder and commands the servo work or do other processes make that uneven?
Group: DynoMotion Message: 10928 From: Tom Kerekes Date: 1/26/2015
Subject: Re: polygonal turning using kflop
Attachments :
Hi Bill.

So it is like you are making a flat on a shaft?  But the opposite inside a hole?  See the attached diagram.

You shouldn't need an interrupt as User Programs run periodically every 180us.

I find that the KFLOP MoveExp works well for constantly commanding a varying position without a need for a trajectory.

I've attached a program as an example.

Regards
TK

Group: DynoMotion Message: 10929 From: bknighton28 Date: 1/26/2015
Subject: Re: polygonal turning using kflop
I cant seem to find a program attached, only a 16K diagram 
Group: DynoMotion Message: 10930 From: Tom Kerekes Date: 1/26/2015
Subject: Re: polygonal turning using kflop
Attachments :
    Hi Bill,

    Not sure how it got lost.  Here it is attached again and pasted in as well:

    Regards
    TK

    #include "KMotionDef.h"

    // Experimental lathe cutting flat

    #define CNTS_PER_REV 4096
    #define INV_CNTS_PER_REV (1.0/((double)CNTS_PER_REV))
    #define ENC 0
    #define XCNTS_PER_INCH 1000.0
    #define XAXIS 0

    // accurately returns the fractional part
    float fractionf(double v);

    // returns spindle angle in radians 0 - 2Pi
    double SpindleAngle(void)
    {
        return fractionf(chan[ENC].Dest * INV_CNTS_PER_REV) * TWO_PI;
    }

    #define L 0.45   // distance from center to Flat
    #define Rc 0.50  // radius

    main()
    {
        double X,Theta,Tmax = acos(L/Rc);  // compute Flat angle range
        while (ReadBit(46))
        {
            Theta = SpindleAngle()-PI;  // get spindle angle and change it to -PI ... +PI
           
            if (Theta < Tmax && Theta >-Tmax)
                X = L/cos(Theta);  // within flat move cutter
            else
                X= Rc; // on round part hold constant
               
            MoveExp(XAXIS,X * XCNTS_PER_INCH,0.002);   // move there exponentially (also delays a TimeSlice)
        }
        Move(XAXIS,Rc * XCNTS_PER_INCH); // retract and stop
        while(!CheckDone(XAXIS)) ;
    }






    Group: DynoMotion Message: 10932 From: bknighton28 Date: 1/26/2015
    Subject: Re: polygonal turning using kflop
    Do I copy my ini file from mach into the main portion of the code?
    Does ENC and XAXIS refer to the channel number? My spindle encoder is the third postion on the snapamp. But it is channel 2.  Would I call it 10 or 2?
    I've tried all variations but will keep working on it  
    I did get the displaySpindleRPMEncoder.c example working from the kmotion429 directory  so there is hope.  
    Group: DynoMotion Message: 10933 From: bknighton28 Date: 1/26/2015
    Subject: Re: polygonal turning using kflop
    I changed return fractionf(chan[ENC].Dest to .Position
    seems to work  
    About to try a cut
    Group: DynoMotion Message: 10934 From: bknighton28 Date: 1/26/2015
    Subject: Re: polygonal turning using kflop
    I added a few lines to feed Z at a specified pitch and it does work. tried 150 rpm.   The cut is not very flat. Just a different curve.  But I was working on .250" stock and the accuracy problem is worse at lower diameters I think.  I am going to work on it tomorrow more and take a video if it works well.  
    Group: DynoMotion Message: 10935 From: Tom Kerekes Date: 1/27/2015
    Subject: Re: polygonal turning using kflop
    Hi Bill,

    What type of Axis is your X axis?  Servo?  Stepper?  What is your resolution?  What kind of acceleration is it capable of?  What final code did you end up with?

    Regards
    TK

    Group: DynoMotion Message: 10936 From: bknighton28 Date: 1/27/2015
    Subject: Re: polygonal turning using kflop
    X and Z are servo  
    This is what I ran.  
    I included the mach init files and changed a line from  .Dest to .Position and added something to advance the z axis  It was cold in my shop and late so as soon as I got something that slightly worked I stopped.  I'm going to try more today or tomorrow.  


    #include "KMotionDef.h"




    // Experimental lathe cutting flat

    #define CNTS_PER_REV 8000
    #define INV_CNTS_PER_REV (1.0/((double)CNTS_PER_REV))
    #define ENC 2
    #define XCNTS_PER_INCH 5000.0
    #define ZCNTS_PER_INCH 10000.0

    #define XAXIS 1
    #define ZAXIS 0

    // accurately returns the fractional part
    float fractionf(double v);

    // returns spindle angle in radians 0 - 2Pi
    double SpindleAngle(void)
    {
        return fractionf(chan[ENC].Position * INV_CNTS_PER_REV) * TWO_PI;
    }

    #define L 0.080  // distance from center to Flat
    #define Rc 0.110  // radius

    main()
    {
    // Z AXIS
    ch0->InputMode=ENCODER_MODE;
    ch0->OutputMode=DC_SERVO_MODE;
    ch0->Vel=2000;
    ch0->Accel=20000;
    ch0->Jerk=150000;
    ch0->P=3;
    ch0->I=0;
    ch0->D=200;
    ch0->FFAccel=0;
    ch0->FFVel=0.02;
    ch0->MaxI=200;
    ch0->MaxErr=1e+006;
    ch0->MaxOutput=200;
    ch0->DeadBandGain=1;
    ch0->DeadBandRange=0;
    ch0->InputChan0=9;
    ch0->InputChan1=0;
    ch0->OutputChan0=9;
    ch0->OutputChan1=0;
    ch0->MasterAxis=-1;
    ch0->LimitSwitchOptions=0x0;
    ch0->InputGain0=1;
    ch0->InputGain1=1;
    ch0->InputOffset0=0;
    ch0->InputOffset1=0;
    ch0->OutputGain=-1;
    ch0->OutputOffset=0;
    ch0->SlaveGain=1;
    ch0->BacklashMode=BACKLASH_OFF;
    ch0->BacklashAmount=0;
    ch0->BacklashRate=0;
    ch0->invDistPerCycle=1;
    ch0->Lead=0;
    ch0->MaxFollowingError=5000;
    ch0->StepperAmplitude=20;

    ch0->iir[0].B0=1;
    ch0->iir[0].B1=0;
    ch0->iir[0].B2=0;
    ch0->iir[0].A1=0;
    ch0->iir[0].A2=0;

    ch0->iir[1].B0=1;
    ch0->iir[1].B1=0;
    ch0->iir[1].B2=0;
    ch0->iir[1].A1=0;
    ch0->iir[1].A2=0;

    ch0->iir[2].B0=1;
    ch0->iir[2].B1=0;
    ch0->iir[2].B2=0;
    ch0->iir[2].A1=0;
    ch0->iir[2].A2=0;

    // X AXIS    
        ch1->InputMode=ENCODER_MODE;
    ch1->OutputMode=DC_SERVO_MODE;
    ch1->Vel=25000;
    ch1->Accel=30000;
    ch1->Jerk=4e+006;
    ch1->P=6;
    ch1->I=0;
    ch1->D=200;
    ch1->FFAccel=0;
    ch1->FFVel=0.02;
    ch1->MaxI=200;
    ch1->MaxErr=1e+006;
    ch1->MaxOutput=200;
    ch1->DeadBandGain=1;
    ch1->DeadBandRange=0;
    ch1->InputChan0=8;
    ch1->InputChan1=0;
    ch1->OutputChan0=8;
    ch1->OutputChan1=0;
    ch1->MasterAxis=-1;
    ch1->LimitSwitchOptions=0x0;
    ch1->InputGain0=1;
    ch1->InputGain1=1;
    ch1->InputOffset0=0;
    ch1->InputOffset1=0;
    ch1->OutputGain=-1;
    ch1->OutputOffset=0;
    ch1->SlaveGain=1;
    ch1->BacklashMode=BACKLASH_OFF;
    ch1->BacklashAmount=0;
    ch1->BacklashRate=0;
    ch1->invDistPerCycle=1;
    ch1->Lead=0;
    ch1->MaxFollowingError=5000;
    ch1->StepperAmplitude=20;

    ch1->iir[0].B0=1;
    ch1->iir[0].B1=0;
    ch1->iir[0].B2=0;
    ch1->iir[0].A1=0;
    ch1->iir[0].A2=0;

    ch1->iir[1].B0=1;
    ch1->iir[1].B1=0;
    ch1->iir[1].B2=0;
    ch1->iir[1].A1=0;
    ch1->iir[1].A2=0;

    ch1->iir[2].B0=0.000769;
    ch1->iir[2].B1=0.001538;
    ch1->iir[2].B2=0.000769;
    ch1->iir[2].A1=1.92081;
    ch1->iir[2].A2=-0.923885;


    //spindle axis for encoder
    ch2->InputMode=ENCODER_MODE;
    ch2->OutputMode=NO_OUTPUT_MODE;
    ch2->Vel=40000;
    ch2->Accel=400000;
    ch2->Jerk=4e+006;
    ch2->P=0;
    ch2->I=0.01;
    ch2->D=0;
    ch2->FFAccel=0;
    ch2->FFVel=0;
    ch2->MaxI=200;
    ch2->MaxErr=1e+006;
    ch2->MaxOutput=200;
    ch2->DeadBandGain=1;
    ch2->DeadBandRange=0;
    ch2->InputChan0=10;
    ch2->InputChan1=0;
    ch2->OutputChan0=2;
    ch2->OutputChan1=0;
    ch2->MasterAxis=-1;
    ch2->LimitSwitchOptions=0x0;
    ch2->InputGain0=-1;
    ch2->InputGain1=1;
    ch2->InputOffset0=0;
    ch2->InputOffset1=0;
    ch2->OutputGain=1;
    ch2->OutputOffset=0;
    ch2->SlaveGain=1;
    ch2->BacklashMode=BACKLASH_OFF;
    ch2->BacklashAmount=0;
    ch2->BacklashRate=0;
    ch2->invDistPerCycle=1;
    ch2->Lead=0;
    ch2->MaxFollowingError=1000000000;
    ch2->StepperAmplitude=20;

    ch2->iir[0].B0=1;
    ch2->iir[0].B1=0;
    ch2->iir[0].B2=0;
    ch2->iir[0].A1=0;
    ch2->iir[0].A2=0;

    ch2->iir[1].B0=1;
    ch2->iir[1].B1=0;
    ch2->iir[1].B2=0;
    ch2->iir[1].A1=0;
    ch2->iir[1].A2=0;

    ch2->iir[2].B0=0.000769;
    ch2->iir[2].B1=0.001538;
    ch2->iir[2].B2=0.000769;
    ch2->iir[2].A1=1.92081;
    ch2->iir[2].A2=-0.923885;

        EnableAxis(0);
        EnableAxis(1);
    EnableAxis(2);
    Zero(0);
    Zero(1);
    Zero(2);

    DefineCoordSystem(1,2,0,-1);
    // peak current limits
    WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT0,11);
    WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT1,11);

    // clamp supply to 90V
    WriteSnapAmp(SNAP0+SNAP_SUPPLY_CLAMP0 ,SNAP_CONVERT_VOLTS_TO_ADC(65.0));
    WriteSnapAmp(SNAP0+SNAP_SUPPLY_CLAMP1 ,SNAP_CONVERT_VOLTS_TO_ADC(65.0));

    // enable supply clamping
    WriteSnapAmp(SNAP0+SNAP_SUPPLY_CLAMP_ENA0 ,1);
    WriteSnapAmp(SNAP0+SNAP_SUPPLY_CLAMP_ENA1 ,1);
        double X,Theta,Tmax = acos(L/Rc);  // compute Flat angle range
        // MoveExp(XAXIS,-0.1 * XCNTS_PER_INCH,0.002); 
        
        double zpos1, zpos2;
        double zmove;    
        double pitch = 0.005; 
        
        zpos1 = chan[ENC].Position;
        zpos2 = zpos1;
        zmove = 0;
        while (ReadBit(46))
        {
            Theta = SpindleAngle()-PI;  // get spindle angle and change it to -PI ... +PI
            
            zpos1 = chan[ENC].Position;
            zmove = zmove + (zpos2 - zpos1) * INV_CNTS_PER_REV * pitch *ZCNTS_PER_INCH ;
            MoveExp(ZAXIS, zmove,0.002);
             
    //printf("%f\n",zmove); 

            if (Theta < Tmax && Theta >-Tmax)
                X = L/cos(Theta);  // within flat move cutter
            else 
                X= Rc; // on round part hold constant
                
                
            MoveExp(XAXIS,X * XCNTS_PER_INCH,0.002);   // move there exponentially (also delays a TimeSlice)
            
            zpos2 = zpos1;
        }
        Move(XAXIS,Rc * XCNTS_PER_INCH); // retract and stop
        while(!CheckDone(XAXIS)) ;
    }

    Group: DynoMotion Message: 10939 From: Tom Kerekes Date: 1/27/2015
    Subject: Re: polygonal turning using kflop
    Hi Bill,

    It seems your X acceleration is set very low.  For this to work well the X axis has to suddenly start moving in quickly.

    I believe your Acceleration is only 30,000 counts/sec2 = 6 in/s2 = 0.015G

    I did a simulation of the required X motion and velocity vs time.  See below and the attached Excel sheet.  The X velocity needs to quickly jump to ~ 1.6ips.  With Acceleration limited to 6in/s2 this would take 0.27 seconds!!

    I'm thinking it would need to be more like 15 milliseconds which would require ~100in/s2 acceleration (~1/4G) or ~500,000 counts/sec2

    The MoveExp command will honor the Acceleration limit specified in the Axis Parameters.

    Is your system's acceleration really that limited? 

    Regards
    TK

    Inline image


    Inline image


    Inline image


    Group: DynoMotion Message: 10945 From: bknighton28 Date: 1/28/2015
    Subject: Re: polygonal turning using kflop
    Attachments :
    It did help some turning up the acceleration to 500,000.  I may not be getting that.  It was still not very flat but I'm going to keep at it.  
    Here's a link to a vid.  It's just a tiny 1/4 rod.  Not much to see.  
    In the pic the flat(ish) area is on top.  
       I hope there isn't any permission problem viewing this.  
    Do you think a kflop c program could address an array of doubles with 8K elements? 
    I'm going to start a python script in rhino right now to divide a polar shape into a set of corresponding x axis values to include in the kflop program so I can make arbitrary shapes. A table who index is the spindle encoder. 
      I'm going to start over with easier shapes with low rate of change.  Maybe a cam lobe.  

     



      @@attachment@@
    Group: DynoMotion Message: 10946 From: Tom Kerekes Date: 1/28/2015
    Subject: Re: polygonal turning using kflop [1 Attachment]
    Hi Bill,

    The video is set to be private.

    You might plot a move on the Step Response Screen of a small distance (0.03 inches = 150 counts), a Velocity of 1.6ips = 8000 counts/sec, Acceleration of 500000counts/s2 and huge jerk 1e8 to check how your system responds and to see if you can optimize tuning for that.

    I noticed the Max Output for X is set for 200.  This is limiting the peak current to 200/1024*35A=6.8A.  High current is needed for high acceleration.

    The first 6 Thread Program Spaces are 64KBytes each.  If you don't use the following thread then it is ok to overflow into it.  Thread #7 is 5x64KBytes.

    doubles are 8 bytes each so an array of 8000 doubles would be 64KBytes.  You might use floats which would be 32KBytes and more than accurate enough.

    Good luck
    TK


    Group: DynoMotion Message: 10947 From: bknighton28 Date: 1/28/2015
    Subject: Re: polygonal turning using kflop [1 Attachment]
    hopefully its public now
    IMG 6237

     



    Group: DynoMotion Message: 10970 From: bknighton28 Date: 1/31/2015
    Subject: Re: polygonal turning using kflop [1 Attachment]
    i've worked a little more on this. I now have a Python program that takes points from a polar shape in Rhino and puts them into an array for the c program on the kflop. the kflop just looks at the encoder and uses the value as an index for the array, moving to the point stored at that cell. in this example there are 1000 points per revolution. I had to reduce it to 1000 points from the resolution of the encoder, which has 8000. I tried running the program in various slots and I could not get the Kflops to accept an array with even 4000 floating point values.
    something I nelgated was tool geometry. in this video the cut going up the cam is good but on the back side of the cam hump parts other than the cutting edge are making context. I'll need to grind an extreme amount of clearance on the tool.
    http://youtu.be/7_bhd0z603g
    Group: DynoMotion Message: 10971 From: bknighton28 Date: 1/31/2015
    Subject: Re: polygonal turning using kflop [1 Attachment]
    The next step should be three-dimensional. A helix of points going from the front of the part all the way to the back with varying radii for each point on the encoder. at a typical lathe feed rate this could be millions of points. there needs to be a way to have the PC feed the Kflops data as it needs it or a little before. maybe it would be possible to attach an accessory to the Kflops with some spare Io lines. Maybe an Arduino that can feed data with extreme reliability. Because if there's a buffer underflow the part is ruined.
    Group: DynoMotion Message: 10984 From: Tom Kerekes Date: 2/2/2015
    Subject: Re: polygonal turning using kflop
    Hi Bill,

    Thanks for the cool video.

    Regarding 3D points:  The gather buffer is 8 MBytes which could hold 2 million single precision floating point values.  But it might be more reasonable to do some sort of 1 or 2D interpolation in a table to reduce the amount of data.

    Another option might be to just use GCode.  It could operate in a similar manner as Threading where the XZ motion is synchronized to the Spindle motion.  That would provide all the buffering and so forth.  KFLOP should be able to handle more than 1000 line segments per second.  I think that might be as fast as your Axes can respond anyway.

    Regards
    TK




    Group: DynoMotion Message: 11022 From: bknighton28 Date: 2/4/2015
    Subject: Re: polygonal turning using kflop
    there is a way to do this with existing G-codes?
    Group: DynoMotion Message: 11028 From: Tom Kerekes Date: 2/5/2015
    Subject: Re: polygonal turning using kflop
    Hi Bill,

    It seems like there should be as I can't see any theoretical difference between what you describe and single-point multi-pass threading.  With single point threading the XZ axis is moved synchronously with the Spindle motion.   See this Video:

     
    Notice the X axis pulls away gradually synchronously with the spindle motion.  Also notice that the Feed Rate needs to be changed to keep the Z motion at the desired rate.   I don't see anything preventing the X motion to be more complex moving in and out more rapidly within each Spindle rotation.  However I'm not sure if there would be details such as download rate, acceleration effects, etc...  that might make it unworkable.

    Regards
    TK